package com.m3958.logcollector.repository;

import java.time.Instant;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import javax.persistence.EntityManager;
import javax.transaction.Transactional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.JpaEntityInformationSupport;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.m3958.logcollector.datacommons.util.AllParams;
import com.m3958.logcollector.datacommons.util.KeyAndCount;
import com.m3958.logcollector.domain.TreeBlob;
import com.m3958.logcollector.service.NextSeqNumber;
import com.m3958.logcollector.specs.TreeBlobSpecs;
import com.m3958.logcollector.tree.Tree;
import com.m3958.logcollector.tree.TreeNode;

public class TreeBlobRepositoryImpl extends SimpleJpaRepository<TreeBlob, Long>implements TreeBlobRepositoryCustom, ApplicationContextAware {

    private static final Logger logger = LoggerFactory.getLogger(TreeBlobRepositoryImpl.class);
    
    @SuppressWarnings("unused")
    private EntityManager entityManager;

    private ApplicationContext context;

    private final JpaEntityInformation<TreeBlob, ?> entityInformation;
    
    @Autowired
    private NextSeqNumber nsn;

    @Autowired
    public TreeBlobRepositoryImpl(EntityManager entityManager) {
        super(TreeBlob.class, entityManager);
        this.entityManager = entityManager;
        this.entityInformation = JpaEntityInformationSupport.getEntityInformation(TreeBlob.class, entityManager);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.springframework.data.jpa.repository.support.SimpleJpaRepository#save(java.lang.Object)
     */
    @Override
    @Transactional
    public <S extends TreeBlob> S save(S entity) {
        if (entityInformation.isNew(entity)) {
            entity.setCreatedAt(Date.from(Instant.now()));
            TreeNode<Map<String, String>> root = new TreeNode<>(nsn.getNextSeqId(), "ROOT");
            Tree<Map<String, String>> idnt = new Tree<Map<String,String>>(root, entity.getName());
            try {
                entity.setTreeContent(context.getBean(ObjectMapper.class).writeValueAsString(idnt));
            } catch (JsonProcessingException e) {
                logger.error("create persongrouptree failed.");
                return null;
            }
        }
        return super.save(entity);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.m3958.datacommons.repository.M3958DataRepository#findQ(com.m3958.datacommons.utils.AllParams, org.springframework.data.domain.Pageable)
     */
    @Override
    public Page<TreeBlob> findQ(AllParams allParams, Pageable pageable) {
        Optional<String> nameOp = allParams.getFirstValue("name");
        if (nameOp.isPresent()) {
            return super.findAll(TreeBlobSpecs.nameIs(nameOp.get()), pageable);
        } else {
            return super.findAll(pageable);
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.m3958.datacommons.repository.M3958DataRepository#keyAndCount(com.m3958.datacommons.utils.AllParams)
     */
    @Override
    public List<KeyAndCount> keyAndCount(AllParams arg0) {
        return null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.m3958.datacommons.repository.M3958DataRepository#updateByPayload(com.fasterxml.jackson.databind.JsonNode, java.lang.Long)
     */
    @Override
    public TreeBlob updateByPayload(JsonNode payload, Long id) {
        if (!payload.path("tree").isMissingNode()) {
            payload = payload.path("tree");
        }
        final JsonNode fpayload = payload;
        return null;
    }

}
